using System;
using System.Threading;
using Microsoft.SPOT.Hardware;
using Gadgeteer;

/*
 * Original Gadgeteer framework Copyright (c) Microsoft Corporation. (http://gadgeteer.codeplex.com/)
 * 
 * Gadgeteer Light made by Stefan Thoolen (http://gadgeteerlight.codeplex.com/)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace SecretLabs.NETMF.Hardware
{
    /// <summary>Represents a generic Go!Module to feed the Go!Socket</summary>
    internal class GoSocketWrapper : GoBus.GoModule
    {
        // The Go!Socket
        private GoBus.GoSocket _socket = null;
        
        // All pins on the socket
        private Cpu.Pin[] _pins;

        /// <summary>Creates a generic Go!Module</summary>
        /// <param name="socket">The socket #</param>
        public GoSocketWrapper(int socket)
        {
            // Defines ourselves
            this._socket = (GoBus.GoSocket)socket;
            // Binds to this socket
            this.BindSocket(this._socket);
            // Starts with the power off
            this.SetSocketPowerState(false);
            // Retrieves all pin numbers
            this._socket.GetPhysicalResources(out this._pins);
            // Powers the socket on
            Thread.Sleep(100);
            this.SetSocketPowerState(true);
            Thread.Sleep(100);
        }

        public Cpu.Pin GetPin(int pin)
        {
            return this._pins[pin - 3];
        }
    }

    internal class NetduinoGo : Board
    {
        static NetduinoGo()
        {
            Board.Hardware = new NetduinoGo();
        }

        private GoSocketWrapper[] _wrappers = new GoSocketWrapper[8];

        /// <summary>Enables a socket</summary>
        /// <param name="socket">The socket number</param>
        private void _ActivateSocket(int socket)
        {
            // Add some code which powers on the socket
            if (_wrappers[socket-1] == null)
                _wrappers[socket - 1] = new GoSocketWrapper(socket);
        }

        /// <summary>Translates a socket pin to a Cpu.Pin</summary>
        /// <param name="socket">The Socket #</param>
        /// <param name="pin">The pin on the socket</param>
        /// <returns>The Cpu.Pin</returns>
        public override Cpu.Pin GetPin(int socket, int pin)
        {
            _ActivateSocket(socket);
            if (pin > 2 && pin < 10)
                return this._wrappers[socket - 1].GetPin(pin);

            return Cpu.Pin.GPIO_NONE;
        }

        /// <summary>Translates a socket to a serial port</summary>
        /// <param name="socket">The Socket #</param>
        /// <returns>The serial port name</returns>
        public override string GetSerial(int socket)
        {
            _ActivateSocket(socket);
            if (socket > 0 && socket < 5)
                return "COM1";
            else if (socket > 4 && socket < 9)
                return "COM2";
            return "N/A";
        }

        /// <summary>Checks if the socket supports the given type</summary>
        /// <param name="socket">The Socket #</param>
        /// <param name="type">Socket type</param>
        /// <returns>true if it's supported</returns>
        public override bool GetSupported(int socket, char type)
        {
            if (type == 'S') return true;
            if (type == 'U') return true;
            if (type == 'X') return true;
            if (type == 'Y') return true;
            return false;
        }

        /// <summary>Creates a new analog input port</summary>
        /// <param name="socket">The socket on which the port exists</param>
        /// <param name="pin">The pin #</param>
        public override AnalogInProvider GetAnalogInProvider(int socket, int pin)
        {
            throw new NotImplementedException();
        }

        /// <summary>Creates a new PWM output port</summary>
        /// <param name="socket">The socket on which the port exists</param>
        /// <param name="pin">The pin #</param>
        public override PWMOutProvider GetPWMOutProvider(int socket, int pin)
        {
            throw new NotImplementedException();
        }
    }
}
